/*
Copyright (c) 2010-2011, Paul Zhang
All rights reserved. 
 */
package cn.dakaqi.utils.img;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author paul
 * @created 2011-3-11
 * 
 */
public class ImageHelper {


	static Logger log = LoggerFactory.getLogger(ImageHelper.class);
	
	
	private static BufferedImage makeThumbnail(BufferedImage img, int width, int height) {
		BufferedImage tag = new BufferedImage(width, height, 1);
		Graphics2D g = tag.createGraphics();
		g.drawImage(img, 0, 0, width,height,null);
		g.dispose();
//		Graphics g = tag.getGraphics();
		tag.getGraphics().drawImage(img.getScaledInstance(width, height, 4), 0, 0, null);
//		g.dispose();
		return tag;
	}

	private static void saveSubImage(BufferedImage image,
			Rectangle subImageBounds, File subImageFile) throws IOException {
		String fileName = subImageFile.getName();
		String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);
		BufferedImage subImage = new BufferedImage(subImageBounds.width,
				subImageBounds.height, 1);
		Graphics g = subImage.getGraphics();
		if ((subImageBounds.width > image.getWidth())
				|| (subImageBounds.height > image.getHeight())) {
			int left = subImageBounds.x;
			int top = subImageBounds.y;
			if (image.getWidth() < subImageBounds.width)
				left = (subImageBounds.width - image.getWidth()) / 2;
			if (image.getHeight() < subImageBounds.height)
				top = (subImageBounds.height - image.getHeight()) / 2;
			g.setColor(Color.white);
			g.fillRect(0, 0, subImageBounds.width, subImageBounds.height);
			g.drawImage(image, left, top, null);
			ImageIO.write(image, formatName, subImageFile);
			//System.out.println("if is running left:" + left + " top: " + top);
		} else {
			g.drawImage(image.getSubimage(subImageBounds.x, subImageBounds.y,
					subImageBounds.width, subImageBounds.height), 0, 0, null);
			//System.out.println("else is running");
		}
		g.dispose();
		ImageIO.write(subImage, formatName, subImageFile);
	}

	public static void cut(String srcImageFile, String descDir, int width,
			int height, Rectangle rect) throws IOException {
		BufferedImage image = ImageIO.read(new File(srcImageFile));
		BufferedImage bImage = makeThumbnail(image, width, height);

		saveSubImage(bImage, rect, new File(descDir));
	}

	public static void cut(File srcImageFile, File descDir, int width,
			int height, Rectangle rect) throws IOException {
		BufferedImage image = ImageIO.read(srcImageFile);
		BufferedImage bImage = makeThumbnail(image, width, height);

		saveSubImage(bImage, rect, descDir);
	}

	/**
	 * 压缩图片
	 * @param imgsrc		原图片物理路径
	 * @param imgdist		新图片保存物理路径
	 * @param widthdist		新图片宽度
	 * @param heightdist	新图片高度
	 */
	public static void reduceImg(String imgsrc, String imgdist, int widthdist,
			int heightdist) {
		try {
			
			File srcfile = new File(imgsrc);
			if (!srcfile.exists()) {
				return;
			}
			Image src = ImageIO.read(srcfile);

			BufferedImage tag = new BufferedImage((int) widthdist,
					(int) heightdist, BufferedImage.TYPE_INT_RGB);

			tag.getGraphics().drawImage(
					src.getScaledInstance(widthdist, heightdist,
							Image.SCALE_SMOOTH), 0, 0, null);

			FileOutputStream out = new FileOutputStream(imgdist);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag);   
			jep.setQuality(1f, true);
			encoder.encode(tag,jep);
			encoder.encode(tag);
			out.close();
			

		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	
	
	
	/**
	 * 获得图片宽度，高度
	 * @param imgsrc
	 * @return result[0]  宽度， result[1] 高度
	 */
	public static int[] getImgSize(String imgsrc){

		int result[]=new int[2];
		
		try {
			
			File   fileOne   =   new   File(imgsrc);
			
			BufferedImage   img   =   ImageIO.read(fileOne);

			result[0]=img.getWidth();
			
			result[1]=img.getHeight();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();log.error(e.getMessage());

		} 
		
		
		return result;
	}
	
	
	
	/**
	 * 图片等比例压缩
	 * @param imgsrc	原图物理路径
	 * @param imgdist	新图片保存物理路径
	 * @param rate		压缩比率   比如 0.8 （80%）， 0.5（50%）  
	 */
	public static void compressImg(String imgsrc,String imgdist,float rate){
		
		//获得原图片宽度高度
		int imgsize[]=getImgSize(imgsrc);

		int widthsrc=imgsize[0];
		
		int heightsrc=imgsize[1];
		
		log.info("--------compressImg-1-------widthsrc:"+widthsrc);
		
		log.info("--------compressImg-1-------heightsrc:"+heightsrc);
		
		//计算获得新图片宽度，高度
		int widthdist=(int) ((int)widthsrc*rate);
		
		int heightdist=(int) ((int)heightsrc*rate);		
		
		//压缩图片
		reduceImg(imgsrc, imgdist, widthdist, heightdist);

	}
	
	
	
	/**
	 * 压缩图片，有宽度，高度上限
	 * @param imgsrc
	 * @param imgdist
	 * @param maxWidth
	 * @param maxHeight
	 * @param rate
	 */
	public static void compressImg(String imgsrc,String imgdist,int maxWidth,int maxHeight,float rate){
		
		
		//获得原图片宽度高度
		int imgsize[]=getImgSize(imgsrc);

		int widthsrc=imgsize[0];
		
		int heightsrc=imgsize[1];
		
		log.info("--------compressImg-2-------widthsrc:"+widthsrc);
		
		log.info("--------compressImg-2-------heightsrc:"+heightsrc);
		
		//如果原图 宽度，高度 没有超过最大宽度，高度，按原尺寸处理
		if(widthsrc<=maxWidth && heightsrc<=maxHeight){
			
			reduceImg(imgsrc, imgdist, widthsrc, heightsrc);
			
			return ;
			
		}
		
		

		//计算获得新图片宽度，高度
		int widthdist=(int) ((int)widthsrc*rate);
		
		int heightdist=(int) ((int)heightsrc*rate);	
		
		log.info("--------compressImg-2-------widthdist:"+widthdist);
		
		log.info("--------compressImg-2-------heightdist:"+heightdist);
		
		//检查宽度，高度是否超过上限
		if(widthdist<=maxWidth && heightdist<=maxHeight){
			
			reduceImg(imgsrc, imgdist, widthdist, heightdist);
			
			return ;
			
		}
		
		
		//如果宽度超过上限，高度没超过上限，计算宽度上限与原宽度的比率，最后等比压缩
		if(widthdist>maxWidth && heightdist<=maxHeight){
			
			float tempRade=(float)maxWidth/(float)widthdist;
			
			//计算新高度
			int lastHeight=(int) ((int)heightdist*tempRade);	
			
			log.info("--------compressImg-2-------lastHeight:"+lastHeight);
			
			reduceImg(imgsrc, imgdist, maxWidth, lastHeight);
			
			return;
		}
		
		//如果宽度没有超过上限，高度超过上线，计算高度上限与原高度的比率，最后等比压缩
		if(widthdist<=maxWidth && heightdist>maxHeight ){
			
			float tempRade=(float)maxHeight/(float)heightdist;
			
			//计算新宽度
			int lastWidth=(int) ((int)widthdist*tempRade);	
			
			log.info("--------compressImg-2-------lastWidth:"+lastWidth);
			
			reduceImg(imgsrc, imgdist, lastWidth, maxHeight);
			
			return;
		
		}
		
		//如果宽度，高度都超过上限，计算宽度上限，高度上限与原宽度，高度比率，最后按比率最小的值等比压缩
		if(widthdist>maxWidth && heightdist>maxHeight){
			
			float tempWidthRade=(float)maxWidth/(float)widthdist;
			
			float tempHeigthRade=(float)maxHeight/(float)heightdist;
	
			//获得最小比率
			float lastRate=tempWidthRade- tempHeigthRade>0?tempHeigthRade:tempWidthRade;
			
			//重新获得高度，宽度
			int lastWidth=(int) ((int)widthdist*lastRate);	
			
			int lastHeight=(int) ((int)heightdist*lastRate);
			
			reduceImg(imgsrc, imgdist, lastWidth, lastHeight);
			
			return;
			
		}
		
	}
	
}
